package com.csaba.connector.otp;

import java.io.IOException;
import java.io.StringReader;
import java.util.logging.Logger;

import net.htmlparser.jericho.Source;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import com.csaba.connector.I18NServiceException;
import com.csaba.connector.ServiceException;
import com.csaba.connector.model.Session;
import com.csaba.connector.otp.model.OTPBank;
import com.csaba.connector.otp.model.OTPRequestFactory;
import com.csaba.connector.otp.model.OTPSession;
import com.csaba.connector.otp.parser.LoginParser;
import com.csaba.connector.service.AbstractBankService;
import com.csaba.util.LoggerHelper;

public class OTPSMSLoginService extends AbstractBankService
{
	private final static Logger logger = LoggerHelper.getDefaultLogger();

	private String smsCode = null;

	// Page displayed before this service called:
	// 		<h1>Bejelentkezés jóváhagyás</h1>
	//        <div class="uzenet input_message">Kérjük, adja meg az alábbi adatokat!</div>
	//		<form name="tranzakcioAlairasForm" method="post" action="/homebank/do/bejelentkezes/bejelentkezesTranzakcioAlairas;jsessionid=v1hFNynThJTKG0PTMzRJ68DP06nBlRLx4Xlqv1x47mhJCGZ2pTWJ!604835461!webapp2!17013!-1!582360980!webapp1!17013!-1" class="repairIEsubmitOnENTER inputForm">
	//        <input type="hidden" name="muveletStatusz" value="bevitel" />
	//        <div class="fieldrow"><label for="smsAzonosito">SMS-ben kapott azonosító</label>          
	//    		<input type="text" name="smsAzonosito" maxlength="8" size="12" value="" id="smsAzonosito" />
	//    	</div>

	@Override
	public void execute( final Session session ) throws ServiceException
	{
		if ( !( session instanceof OTPSession ) )
			throw new ServiceException("Unsupported session for OTP services: " + session.getClass().getName());

		final OTPSession otp = (OTPSession) session;

		// PostElements:
		//		muveletStatusz=bevitel
		//		smsAzonosito=83606347
		//		formButtons(elkuld).x=24 //double URL encoding
		//		formButtons(elkuld).y=4

		final NameValuePair[] loginData = new NameValuePair[] {// 
		//
				new BasicNameValuePair("muveletStatusz", "bevitel"), //
				new BasicNameValuePair("smsAzonosito", smsCode), // 
				new BasicNameValuePair("formButtons(elkuld).x", "22"), //
				new BasicNameValuePair("formButtons(elkuld).y", "11"), //
		};

		// Request URL:
		//   	https://www.otpbankdirekt.hu/homebank/do/bejelentkezes/bejelentkezesTranzakcioAlairas;jsessionid=<session-id>
		final String smsLoginResult = otp.doPost(OTPRequestFactory.HOMEBANK_REQUEST_URL_BASE
				+ OTPRequestFactory.REQUEST_SMSLOGIN, loginData);

		otp.debugFile("smsLoginReply1", smsLoginResult);

		// Transaction polling:
		//		https://www.otpbankdirekt.hu/homebank/do/pollTransactionAnswer;jsessionid=<session-id>?folyamatId=JOVAHAGYASKULDES;2042640318;10.42.2.121&workflow=JOVAHAGYASKULDES
		String result = null;

		//parse poll instruction
		final String pollUrl = TransactionPolling.parsePollTransaction(smsLoginResult);
		if ( pollUrl != null )
		{
			logger.fine("Poll transaction URL: " + pollUrl);

			if ( !( new TransactionPolling(otp, pollUrl) ).poll() )
				throw new I18NServiceException(OTPBank.getInstance(), "msg.smsLoginTimeout");
			//get the result, after poll
			// PostElements:
			//		kliensTranzakcioId=1
			//		muveletStatusz=varakozas
			final NameValuePair[] data = new NameValuePair[] {
					new BasicNameValuePair("kliensTranzakcioId", String.valueOf(otp.getOperationCounter())),
					new BasicNameValuePair("muveletStatusz", "varakozas"), };

			// Reload:
			// 		https://www.otpbankdirekt.hu/homebank/do/bejelentkezes/bejelentkezesTranzakcioAlairas;jsessionid=<session-id>
			result = otp.doPost(OTPRequestFactory.HOMEBANK_REQUEST_URL_BASE + OTPRequestFactory.REQUEST_SMSLOGIN, data);
			otp.debugFile("smsLoginReply", result);
		}
		else
		{ //the account list may be already returned.
			result = smsLoginResult;
		}

		//decide on error 
		Source source;
		try
		{
			source = new Source(new StringReader(result));
		}
		catch ( final IOException e )
		{
			throw new I18NServiceException(OTPBank.getInstance(), "msg.loginError1", e);
		}

		if ( LoginParser.isErrorOccuredSMSLogin(result) )
		{
			logger.fine("Error during login... Parsing messaging.");
			String message = null;
			try
			{
				message = LoginParser.parseSMSLoginError(source);
			}
			catch ( final Exception ex )
			{
				throw new I18NServiceException(OTPBank.getInstance(), "msg.loginError1", ex);
			}

			throw new I18NServiceException(OTPBank.getInstance(), "msg.loginError2", message);
		}
		else
		{
			//normal password login
			OTPLoginService.postProcessLogin(otp, result, source);
		}
	}

	public void setSmsCode( final String smsCode )
	{
		this.smsCode = smsCode;
	}

}
